#include "CTest.h"

CTest::CTest()
{
    listQuestion = new CListQuestion();
    pageSettings = new CPageSettings();
    this->printSettings.setPageSettings(pageSettings);
}

CTest::~CTest()
{
//    delete listQuestion;
//    delete pageSettings;
}

CListQuestion CTest::getListQuestion()
{
    return *(this->listQuestion);
}

void CTest::setListQuestion(CListQuestion lq)
{
    *(this->listQuestion) = lq;
}

/**
  * Метод удаляет узел из dom-модели документа. Всегда удаляется узел Question.
  * \a i - номер удаляемого узла
  */
void CTest::removeChildFormDomDocument(int n)
{
    QDomNodeList domNodeList = this->domDocument.documentElement().firstChildElement("Tests").childNodes();
    this->domDocument.documentElement().firstChildElement("Tests").removeChild(domNodeList.at(n));
}

/**
 * Метод вызывается для разбора DOM-модели XML-документа,
 * которая может быть получена с помощью CFileTest
 * \a domDoc - dom-модель документа для разбора
 */
bool CTest::parseDomDocument(QDomDocument domDoc)
{
    //Парсим данные
    this->domDocument = domDoc;
    QDomElement domElement = this->domDocument.documentElement(); //Получаем корневой элемент (<Tests>)
    QDomNodeList domNodeList = domElement.firstChildElement("Tests").childNodes(); //Получаем все дочерние узлы узла Tests
    for (int i=0; i<domNodeList.count(); i++)
    {
        CQuestion quest;
        //Поочередный рекурсивный обход дочерних узлов корневого узла
        //Результат обхода помещается в объект класса CQuestion
        traverseTestNode(domNodeList.item(i), quest);
        //Добавление вопроса в список вопросов
        listQuestion->addQuestion(quest);
    }
    //Парсим настройки документа
    QDomNodeList settings;
    QDomNodeList printSettings;
    QDomNodeList pageSettingsNode;
    settings = domElement.firstChildElement("Settings").childNodes();
    //Парсим настройки печати
    if (!settings.isEmpty())
	for (int i=0; i<settings.count(); i++)
	{
	    if (settings.at(i).toElement().tagName() == "printSettings")
	    {
		printSettings = settings.at(i).childNodes();
		CPagination p;
		for (int j=0; j<printSettings.count(); j++)
		{
		    if (printSettings.at(j).toElement().tagName() == "pagination")
			p.setPagination(QVariant(printSettings.at(j).toElement().text()).toBool());
		    if (printSettings.at(j).toElement().tagName() == "location")
			p.setLocation(static_cast<CPagination::Location>(printSettings.at(j).toElement().text().toInt()));
		    if (printSettings.at(j).toElement().tagName() == "alignment")
			p.setAlignment(static_cast<CPagination::Alignment>(printSettings.at(j).toElement().text().toInt()));
		    if (printSettings.at(j).toElement().tagName() == "firstPageNumbered")
			p.setFirstPageNumbered(QVariant(printSettings.at(j).toElement().text()).toBool());
		    if (printSettings.at(j).toElement().tagName() == "startPage")
			p.setStartPage(QVariant(printSettings.at(j).toElement().text()).toInt());
		}
		this->printSettings.setPagination(p);
	    }
            else
            if ((settings.at(i).toElement().tagName() == "pageSettings"))
            {
		pageSettingsNode = settings.at(i).childNodes();
//                CPageSettings *p = 0;
		for (int j=0; j<pageSettingsNode.count(); j++)
                {
		    if (pageSettingsNode.at(j).toElement().tagName() == "orientation")
			pageSettings->setOrientation(static_cast<CPageSettings::Orientation>(pageSettingsNode.at(j).toElement().text().toInt()));
		    if (pageSettingsNode.at(j).toElement().tagName() == "paperSize")
			pageSettings->setPaperSize(static_cast<CPageSettings::PaperSize>(pageSettingsNode.at(j).toElement().text().toInt()));
		    if (pageSettingsNode.at(j).toElement().tagName() == "margins")
                    {
                        QDomNodeList marginsList;
			marginsList = pageSettingsNode.at(j).toElement().childNodes();
                        qreal top=0, left=0, bottom=0, right=0;
                        for (int k=0; k<marginsList.count(); k++)
                        {
                            if (marginsList.at(k).toElement().tagName() == "top")
                            {
                                top = marginsList.at(k).toElement().text().toDouble();
                            }
                            else
                            if (marginsList.at(k).toElement().tagName() == "bottom")
                            {
                                bottom = marginsList.at(k).toElement().text().toDouble();
                            }
                            if (marginsList.at(k).toElement().tagName() == "left")
                            {
                                left = marginsList.at(k).toElement().text().toDouble();
                            }
                            if (marginsList.at(k).toElement().tagName() == "right")
                            {
                                right = marginsList.at(k).toElement().text().toDouble();
                            }
                        }
			pageSettings->setPageMargins(left, top, right, bottom, CPageSettings::Millimeter);
                    }
                }
		qDebug()<<"CTest::parseDomDocument"<<pageSettings->orientation();
		this->printSettings.setPageSettings(pageSettings);
            }
        }

    return true;
}
//------------------------------------------------------------------------------------------
/**
 * Метод формирует dom-модель документа, которая затем может быть сохранена в хмл-файл.
 * В зависимости от возвращаемого значения методом isNew()
 * добавляет вопрос в существующую dom-модель, либо обновляет вопрос.
 * Метод CTest::createDomElementTest формирует добавляемый dom-элемент.
 * Также метод сохраняет настройки печати в dom-модель.
 */
QDomDocument CTest::getDomDocument()
{
    // Формируем dom-модель данных
    for (int i=0; i < listQuestion->count(); i++)
    {
        if (listQuestion->getQuestion(i).isNew())
        {
            QDomElement domElement = createDomElementTest(listQuestion->getQuestion(i), i);
	    this->domDocument.documentElement().firstChildElement("Tests").appendChild(domElement);
            listQuestion->question[i].setNew(false);
            listQuestion->question[i].changed(false);
        }
        if (listQuestion->getQuestion(i).isChanged())
        {
	    QDomNodeList domNodeList = domDocument.documentElement().firstChildElement("Tests").childNodes();
	    QDomNode questNode = domNodeList.at(i);
            QDomElement domElement = createDomElementTest(listQuestion->getQuestion(i), i);
	    this->domDocument.documentElement().firstChildElement("Tests").replaceChild(domElement, questNode);
            listQuestion->question[i].changed(false);
        }
    }

    // Добавляем в dom-модель настройки печати
    QDomElement child = domDocument.createElement("printSettings");
    QDomNode node = domDocument.createElement("pagination");
    QDomText text = domDocument.createTextNode(QVariant(this->printSettings.getPagination().isPagination()).toString());
    node.appendChild(text);
    child.appendChild(node);

    node = domDocument.createElement("location");
    text = domDocument.createTextNode(QVariant(this->printSettings.getPagination().getLocation()).toString());
    node.appendChild(text);
    child.appendChild(node);

    node = domDocument.createElement("alignment");
    text = domDocument.createTextNode(QVariant(this->printSettings.getPagination().getAlignment()).toString());
    node.appendChild(text);
    child.appendChild(node);

    node = domDocument.createElement("firstPageNumbered");
    text = domDocument.createTextNode(QVariant(this->printSettings.getPagination().getFirstPageNumbered()).toString());
    node.appendChild(text);
    child.appendChild(node);

    node = domDocument.createElement("startPage");
    text = domDocument.createTextNode(QVariant(this->printSettings.getPagination().getStartPage()).toString());
    node.appendChild(text);
    child.appendChild(node);

    QDomNode oldChild;
    oldChild = domDocument.documentElement().firstChildElement("Settings").firstChildElement("printSettings");
    domDocument.documentElement().firstChildElement("Settings").replaceChild(child, oldChild);

    //Добавляем в dom-модель настройки страницы
    QDomElement pageElement = domDocument.createElement("pageSettings");
    node = domDocument.createElement("orientation");
    text = domDocument.createTextNode(QVariant(this->printSettings.getPageSettings()->orientation()).toString());
    node.appendChild(text);
    pageElement.appendChild(node);

    node = domDocument.createElement("paperSize");
    text = domDocument.createTextNode(QVariant(this->printSettings.getPageSettings()->paperSize()).toString());
    node.appendChild(text);
    pageElement.appendChild(node);

    node = domDocument.createElement("margins");
    QDomNode marginsNode = pageElement.appendChild(node);
    QDomElement marginsElement = marginsNode.toElement();

    qreal top, bottom, left, right;
    this->printSettings.getPageSettings()->getPageMargins(&left, &top, &right, &bottom, CPageSettings::Millimeter);
//    qDebug()<<top<<bottom, left, right;
    node = domDocument.createElement("top");
    text = domDocument.createTextNode(QVariant(top).toString());
    node.appendChild(text);
    marginsElement.appendChild(node);

    node = domDocument.createElement("left");
    text = domDocument.createTextNode(QVariant(left).toString());
    node.appendChild(text);
    marginsElement.appendChild(node);

    node = domDocument.createElement("right");
    text = domDocument.createTextNode(QVariant(right).toString());
    node.appendChild(text);
    marginsElement.appendChild(node);

    node = domDocument.createElement("bottom");
    text = domDocument.createTextNode(QVariant(bottom).toString());
    node.appendChild(text);
    marginsElement.appendChild(node);

    oldChild = domDocument.documentElement().firstChildElement("Settings").firstChildElement("pageSettings");
    domDocument.documentElement().firstChildElement("Settings").replaceChild(pageElement, oldChild);

    return this->domDocument;
}
//------------------------------------------------------------------------------------------

/**
 * Метод производит реккурсивный обход dom-узла node xml-документа
 * Результат работы метода сохранается в quest
 */
void CTest::traverseTestNode(const QDomNode &node, CQuestion &quest)
{
    QDomNode domNode = node.firstChild();
    while (!domNode.isNull())
    {
        if (domNode.isElement())
        {
            QDomElement domElement = domNode.toElement();
            if (!domElement.isNull())
            {
                if (node.toElement().tagName() == "test")
                {
                    quest.setQuestionType(node.toElement().attribute("whoAmI", "").toInt());
                }
                if (domElement.tagName() == "questionText")
                {
                    quest.setTextQuestion(domElement.text());
                }
                else
                if (domElement.tagName() == "answerText")
                {
                    CListAnswer la = quest.getListAnswer();
                    CAnswer a = la.lastAnswer();
                    a.setTextAnswer(domElement.text());
                    la.addAnswer(a);
                    quest.setListAnswer(la);
                }
                else
                if (domElement.tagName() == "rightAnswer")
                {
                    CListAnswer la = quest.getListAnswer();
                    CAnswer a = la.lastAnswer();
                    a.setRightAnswer(QVariant(domElement.text()).toBool());
                    la.updateAnswer(a, la.lastIndex());
                    quest.setListAnswer(la);
                }
                else
                if (domElement.tagName() == "textComment")
                {
		    quest.setComment(domElement.text());
                }
            }
        }
        traverseTestNode(domNode, quest);
        domNode = domNode.nextSibling();
    }
}
//------------------------------------------------------------------------------------------

/**
 * Метод формирует добавляемый dom-элемент на основе объекта t класса CQuestion.
 * \a  t - ссылка на объекта CQuestion, на основе которого формируется dom-элемент.
 * \a testNum - номер добавляемого вопроса
 */
QDomElement CTest::createDomElementTest(const CQuestion &t, int testNum)
{
    //Формируем элемент test
    QDomElement domElement = domDocument.createElement("test");
    domElement.setAttribute("whoAmI", t.getQuestionType());
    domElement.setAttribute("num", testNum);

    //Формируем дочерний элемент question
    QDomElement question = domDocument.createElement("question");
    //Узел с текстом вопроса
    QDomElement questionText = domDocument.createElement("questionText");
    QDomText text = domDocument.createTextNode(t.getTextQuestion()); 
    questionText.appendChild(text);
    //Узел с текстом коментария
    text.clear();
    QDomElement commentText = domDocument.createElement("textComment");
    text = domDocument.createTextNode(t.getComment());
    commentText.appendChild(text);

    question.appendChild(questionText);
    question.appendChild(commentText);
    //Добавляем question к test
    domElement.appendChild(question);

    //Теперь делаем дочерний элемент answers
    QDomElement answers = domDocument.createElement("answers");
    //И создаем потомков узла answers.
    for (int i = 0; i<t.getListAnswer().count(); i++)
    {
        //создаем узел <answer number=id/>
        QDomElement answer = domDocument.createElement("answer");
        answer.setAttribute("number", i);
        //создаем узел <answerText>
        QDomElement answerText = domDocument.createElement("answerText");
        text = domDocument.createTextNode(t.getListAnswer().getAnswer(i).getTextAnswer());
        answerText.appendChild(text);
        //создаем узел <rightAnswerText>
        QDomElement rightAnswerText = domDocument.createElement("rightAnswer");
        text = domDocument.createTextNode(QVariant(t.getListAnswer().getAnswer(i).isRightAnswer()).toString());
        rightAnswerText.appendChild(text);


        //Добавляем созданные узлы к answer
        answer.appendChild(answerText);
        answer.appendChild(rightAnswerText);
        //Добавляем answer в общую кучу answers
        answers.appendChild(answer);
    }
    //Добавляем answers к test
    domElement.appendChild(answers);

    return domElement;
}

void CTest::setPrintSettings(CPrintSettings ps)
{
    this->printSettings = ps;
}

CPrintSettings CTest::getPrintSettings()
{
    qDebug()<<"CTest::getPrintSettings()"<<printSettings.getPageSettings();
    return this->printSettings;
}
